﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using Microsoft.Win32;

namespace FNFSync
{
    public partial class FnFSyncMainForm : Form
    {
        void populateTreeView(TreeView tvTree, int iFolderType)
        {
            tvTree.Nodes.Clear();
        }

        public FnFSyncMainForm()
        {
            InitializeComponent();
            this.Resize += new EventHandler(Form1_Resize);
        }

        /// <summary>
        /// Handles the Load event of the FnFSyncMainForm control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void FnFSyncMainForm_Load(object sender, EventArgs e)
        {
            try
            {
                appStartup = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
                chkbxStartup.Enabled = true;
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.ToString(), "Error", MessageBoxButtons.OK);
                this.toolTip1.SetToolTip(this.chkbxStartup, "Disabled because you don't have enough permissions to write to registry");
                chkbxStartup.Enabled = false;
            }
            //Application setting


            switch (FNFSync.Properties.Settings.Default.SyncDirections)
            {
                case "Sync Down":
                    rBtnDown.Checked = true;
                    chkbxMonitorPrimary.Enabled = true;
                    chlbxMonitorSecondary.Enabled = false;
                    break;
                case "Sync Up":
                    rBtnSyncUp.Checked = true;
                    chlbxMonitorSecondary.Enabled = true;
                    chkbxMonitorPrimary.Enabled = false;
                    break;
                case "Two Way Sync":
                    rBtn2WaySync.Checked = true;
                    chkbxMonitorPrimary.Enabled = false;
                    chlbxMonitorSecondary.Enabled = false;
                    break;
            }
            //try
            //{
            //    string xyzt = FNFSync.Properties.Settings.Default.PrimaryLocation;
            //    //txtFolderLocn2.Text = FNFSync.Properties.Settings.Default.SecondaryLocation;
            //}
            //catch (System.Exception ex)
            //{
            //}
            switch (FNFSync.Properties.Settings.Default.SyncOptions)
            {
                case "Copy Non-Existent":
                    rBtnCopyNonExistent.Checked = true;
                    break;
                case "Overwrite Older Version":
                    rBtnLatestVersion.Checked = true;
                    break;
                case "Always Overwrite":
                    rBtnAlwaysOverwrite.Checked = true;
                    break;
            }

            switch (FNFSync.Properties.Settings.Default.VerboseLevel)
            {
                case "Level 1":
                    if (!level1ToolStripMenuItem.Checked)
                    {
                        level1ToolStripMenuItem.Checked = true;
                        level2ToolStripMenuItem.Checked = false;
                        l3ToolStripMenuItem.Checked = false;

                        toolTip1.SetToolTip(this.listBoxMessageCenter, "Message Center @ Verbose Level 1");
                        listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + "Verbose Level 1 activated");
                    }
                    break;

                case "Level 2":
                    if (!level2ToolStripMenuItem.Checked)
                    {
                        level2ToolStripMenuItem.Checked = true;
                        level1ToolStripMenuItem.Checked = false;
                        l3ToolStripMenuItem.Checked = false;
                        listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + "Verbose Level 2 activated");
                        toolTip1.SetToolTip(this.listBoxMessageCenter, "Message Center @ Verbose Level 2");
                    }
                    else
                    {
                        level2ToolStripMenuItem.Checked = false;
                        level1ToolStripMenuItem.Checked = true;
                        listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + "Reverted to default verbose level");
                        toolTip1.SetToolTip(this.listBoxMessageCenter, "Message Center @ Verbose Level 1");
                    }
                    break;

                case "Level 3":
                    if (!l3ToolStripMenuItem.Checked)
                    {
                        l3ToolStripMenuItem.Checked = true;
                        level1ToolStripMenuItem.Checked = false;
                        level2ToolStripMenuItem.Checked = false;
                        listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + "Verbose Level 3 activated");
                        toolTip1.SetToolTip(this.listBoxMessageCenter, "Message Center @ Verbose Level 3");
                    }
                    else
                    {
                        l3ToolStripMenuItem.Checked = false;
                        level1ToolStripMenuItem.Checked = true;
                        listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + "Reverted to default verbose level");
                        toolTip1.SetToolTip(this.listBoxMessageCenter, "Message Center @ Verbose Level 1");
                    }
                    break;

            }

            switch (FNFSync.Properties.Settings.Default.CloseOnComplete)
            {
                case "Yes":
                    chkBxCloseApp.Checked = true;
                    break;

                case "No":
                    chkBxCloseApp.Checked = false;
                    break;
            }

            if (appStartup.GetValue("FNFSync") == null)
            {
                chkbxStartup.Checked = false;
            }
            else
            {
                chkbxStartup.Checked = true;
            }
        }

        /// <summary>
        /// Handles the Resize event of the Form1 control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void Form1_Resize(object sender, EventArgs e)
        {
            if (WindowState == FormWindowState.Minimized)
            {
                Hide();
                notifyIcon1.Visible = true;
            }
            else
                notifyIcon1.Visible = false;
        }

        /// <summary>
        /// Enum for Sync Options we provide to customers
        /// </summary>
        private enum enmSyncOption { CopyNonExistent=1, LatestVersion, AlwaysOverwrite };
        private enum enmVerboseLevel { Level1 = 1, Level2, Level3 };

        /// <summary>
        /// Enum for Type of Folders - Ex Normal, FTP etc
        /// </summary>
        private enum enmFolderType { Local = 0, Network, FTP };

        /// <summary>
        /// Object of cFolderSync.
        /// </summary>
        cFolderSync oFolderSync = new cFolderSync
        {
            bFolderLocation1Validated = false,
            bFolderLocation2Validated = false,
            sPrimaryLocation = string.Empty,
            sSecondaryLocation = string.Empty,
            diDirInfoLocn1 = null,
            diDirInfoLocn2 = null,
            iPrimaryFolderSize = -1,
            iSecondaryFolderSize = -1,
            TwoWaySyncInitiationComplete=false
        };//Just Initialized object in a new manner...Enhancement in .NET 3.5

        /// <summary>
        /// Class for Holding the DirectoryInfo for the paths (primary and secondary). Depending on the direction of
        /// sync chosen, location 1 might have DirectoryInfo for secondary location
        /// </summary>
        private class orderOfParams
        {
            public DirectoryInfo _dirInfoLocn1 { get; internal set; }
            public DirectoryInfo _dirInfoLocn2 { get; internal set; }
        }
        
        /// <summary>
        /// Used to track start time and end time for sync -- Approximate though
        /// </summary>
        DateTime tStartTime;
        DateTime tEndTime;

        #region Global Strings used for updating UI controls. Workaround used..
        
        string g_sFileName=string.Empty;
        string g_sCompleteFileName=string.Empty;
        
        #endregion

        int iPercentComplete = 0;

        private ManualResetEvent mseSyncWorkerLocker = new ManualResetEvent(true);
        RegistryKey appStartup;
                
            


        /// <summary>
        /// Handles the Click event for the Ellipsis button for selecting the location. We use FolderBrowserDialog
        /// to achieve our goal
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnSelectFolderLocn1_Click(object sender, EventArgs e)
        {
            dlgFolderBrowser.ShowDialog();
            FnFSyncMainForm.ActiveForm.Text = "FNFSync";
            if (dlgFolderBrowser.SelectedPath != "")
            {
                txtFolderLocn1.Text = dlgFolderBrowser.SelectedPath;
                oFolderSync.bFolderLocation1Validated = true;
                oFolderSync.sPrimaryLocation = dlgFolderBrowser.SelectedPath;
                txtFolderLocn1.BackColor = System.Drawing.Color.DarkSeaGreen;
                lblStatusMsg.Text = "Primary location is valid";
                listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + oFolderSync.sPrimaryLocation + " is identified as a valid location.");

                txtFolderLocn2.Enabled = true;
                btnSelectFolderLocn2.Enabled = true;
                btnValidateLocn2.Enabled = true;
            }

        }

        /// <summary>
        /// Handles the Click event for the Ellipsis button for selecting the location. We use FolderBrowserDialog
        /// to achieve our goal
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnSelectFolderLocn2_Click(object sender, EventArgs e)
        {
            FnFSyncMainForm.ActiveForm.Text = "FNFSync";
            dlgFolderBrowser.ShowDialog();
            if (dlgFolderBrowser.SelectedPath != "")
            {
                txtFolderLocn2.Text = dlgFolderBrowser.SelectedPath;
                oFolderSync.bFolderLocation2Validated = true;
                oFolderSync.sSecondaryLocation = dlgFolderBrowser.SelectedPath;
                txtFolderLocn2.BackColor = System.Drawing.Color.DarkSeaGreen;
                lblStatusMsg.Text = "Secondary location is valid";
                listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + oFolderSync.sSecondaryLocation + " is identified as a valid location.");

            }
        }

        /// <summary>
        /// Handles the Click event for the configure button. This not implemented yet
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnConfigure_Click(object sender, EventArgs e)
        {
            FnFSyncMainForm.ActiveForm.Text = "FNFSync";
            Preferences preferences = new Preferences();
            preferences.ShowDialog();
        }

        /// <summary>
        /// Handles the click event for the Stop button. This sends the Cancel for the Background worker
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnStopSync_Click(object sender, EventArgs e)
        {
            bWorkerSync.CancelAsync();
            FnFSyncMainForm.ActiveForm.Text = "FNFSync - Cancelling Syncronization...";
            listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + "Syncronization is cancelled.");

        }

        /// <summary>
        /// Handles the Click event of the showToolStripMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void showToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Show();
            WindowState = FormWindowState.Normal;
        }

        /// <summary>
        /// handles Click event for the Pause sync button and "Resets" the ManualResetEvent locker
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnPauseSync_Click(object sender, EventArgs e)
        {
            mseSyncWorkerLocker.Reset();
            btnPauseSync.Enabled = false;
            btnResumeSync.Enabled = true;
            lblStatusMsg.Text = "...sync is currently paused";
            FnFSyncMainForm.ActiveForm.Text = "FNFSync - Sync is pausing... " + iPercentComplete + "% complete till now.";
            listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + "FNFSync - Sync is paused... " + iPercentComplete + "% complete till now." + " " + g_sFileName + " is the last file syncronized");

        }

        /// <summary>
        /// handles Click event for the Resume sync button and "Sets" the ManualResetEvent locker
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnResumeSync_Click(object sender, EventArgs e)
        {
            mseSyncWorkerLocker.Set();
            btnResumeSync.Enabled = false;
            btnPauseSync.Enabled = true;
            lblStatusMsg.Text = "Currently syncronizing...";
            listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + "Sync resumed by user again");

        }

        /// <summary>
        /// handles Click event for the Info button and displays the About box
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnInfo_Click(object sender, EventArgs e)
        {
            /// AboutBox1.
            AboutBox1 abtbox = new AboutBox1();
            abtbox.ShowDialog();
        }

        /// <summary>
        /// Handles Click event for the Sync button on the frame. We do some basic form level initialization. We check the
        /// sync direction chosen, set the order appropriately and send to the Sync function.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnSyncNonExistingFiles_Click(object sender, EventArgs e)
        {

            if (oFolderSync.bFolderLocation1Validated == true && oFolderSync.bFolderLocation2Validated == true)
            {
                gBoxButtons.Enabled = false;
                gBoxSyncOptions.Enabled = false;

                progressBarSync.Value = 0;
                btnSyncNonExistingFiles.Enabled = false;
                btnResumeSync.Enabled = false;
                btnPauseSync.Enabled = true;
                btnStopSync.Enabled = true;


                if (rBtnSyncUp.Checked == true)
                {
                    chlbxMonitorSecondary.Enabled = true;
                    chkbxMonitorPrimary.Enabled = false;

                    progressBarSync.Maximum = Convert.ToInt32(oFolderSync.iSecondaryFolderSize);
                    if (progressBarSync.Maximum <= 0)
                    {
                        progressBarSync.Maximum = 1;
                    }
                    oFolderSync.sPrimaryLocation = txtFolderLocn2.Text;
                    oFolderSync.sSecondaryLocation = txtFolderLocn1.Text;
                    Sync(oFolderSync.diDirInfoLocn2, oFolderSync.diDirInfoLocn1);
                }
                else if (rBtnDown.Checked == true)
                {
                    chkbxMonitorPrimary.Enabled = true;
                    chlbxMonitorSecondary.Enabled = false;
                    progressBarSync.Maximum = Convert.ToInt32(oFolderSync.iPrimaryFolderSize);
                    if (progressBarSync.Maximum <= 0)
                    {
                        progressBarSync.Maximum = 1;
                    }
                    oFolderSync.sPrimaryLocation = txtFolderLocn1.Text;
                    oFolderSync.sSecondaryLocation = txtFolderLocn2.Text;
                    Sync(oFolderSync.diDirInfoLocn1, oFolderSync.diDirInfoLocn2);
                }
                else if (rBtn2WaySync.Checked == true)
                {
                    chlbxMonitorSecondary.Enabled = false;
                    chkbxMonitorPrimary.Enabled = false;

                    oFolderSync.TwoWaySyncInitiationComplete = false;
                    progressBarSync.Maximum = Convert.ToInt32(oFolderSync.iSecondaryFolderSize + oFolderSync.iPrimaryFolderSize);
                    if (progressBarSync.Maximum <= 0)
                    {
                        progressBarSync.Maximum = 1;
                    }
                    oFolderSync.sPrimaryLocation = txtFolderLocn2.Text;
                    oFolderSync.sSecondaryLocation = txtFolderLocn1.Text;
                    Sync(oFolderSync.diDirInfoLocn2, oFolderSync.diDirInfoLocn1);

                }
                lblStatusMsg.Text = "Currently Syncronizing...";
                listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + "Syncronization started");
                tStartTime = DateTime.Now;
                    
            }
            else
            {
                lblStatusMsg.Text = "Primary and/or Secondary locations not yet validated";
                listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + "Primary and/or Secondary file location not validated yet");
            }
        }

        /// <summary>
        /// Function, where we accept the DirectoryInfo type. We set the appropriate order previously and send accordingly
        /// to this function. So the _dirInfoLocn1 can be the DirectoryInfo for the Secondary location.
        /// </summary>
        /// <param name="_dirInfoLocn1">The _dirinfolocn1.</param>
        /// <param name="_dirInfoLocn2">The _dirinfolocn2.</param>
        private void Sync(DirectoryInfo _dirInfoLocn1, DirectoryInfo _dirInfoLocn2)
        {

            orderOfParams oOrderoOfParams = new orderOfParams();
            oOrderoOfParams._dirInfoLocn1 = _dirInfoLocn1;
            oOrderoOfParams._dirInfoLocn2 = _dirInfoLocn2;
            while (!(bWorkerSync.IsBusy))
                bWorkerSync.RunWorkerAsync(oOrderoOfParams);
        }

        /// <summary>
        /// Handles the DoWork event of the bWorkerSync control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.ComponentModel.DoWorkEventArgs"/> instance containing the event data.</param>
        private void bWorkerSync_DoWork(object sender, DoWorkEventArgs e)
        {
            int syncOptions = 0;
            if (rBtnCopyNonExistent.Checked)
            {
                syncOptions = (int)(enmSyncOption.CopyNonExistent);
            }
            else if (rBtnAlwaysOverwrite.Checked)
            {
                syncOptions = (int)(enmSyncOption.AlwaysOverwrite);
            }
            else if (rBtnLatestVersion.Checked)
            {
                syncOptions = (int)(enmSyncOption.LatestVersion);
            }

            orderOfParams argument = e.Argument as orderOfParams;
            DirectoryInfo[] dirInfoArrayPrimary = argument._dirInfoLocn1.GetDirectories();
            //DirectoryInfo[] dirInfoArraySecondary = _dirInfoLocn2.GetDirectories();

            foreach (DirectoryInfo dirInfoPrimary_Temp in dirInfoArrayPrimary)
            {
                if (bWorkerSync.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }
                mseSyncWorkerLocker.WaitOne();

                try
                {
                    if (!(Directory.Exists(oFolderSync.sSecondaryLocation + @"\" + dirInfoPrimary_Temp.Name)))
                        Directory.CreateDirectory(oFolderSync.sSecondaryLocation + @"\" + dirInfoPrimary_Temp.Name);
                }
                catch (System.Exception ex)
                {
                    MessageBox.Show(ex.Message + "\nAborting the operation");
                    e.Cancel = true;
                    return;
                }

                recursiveDirectoryCalls(dirInfoPrimary_Temp, oFolderSync.sSecondaryLocation, syncOptions, e);

            }

            //After all sub folder'sd work is done then we proceed to copying all files in the root
            FileInfo[] fileInfoPrimary = argument._dirInfoLocn1.GetFiles();

            //FileInfo[] fileInfoSecondary = _dirInfoLocn2.GetFiles();

            foreach (FileInfo fileInfoPrimary_temp in fileInfoPrimary)
            {
                if (bWorkerSync.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }

                mseSyncWorkerLocker.WaitOne();

                switch (syncOptions)
                {
                    case (int)enmSyncOption.CopyNonExistent:
                        if (!(File.Exists(argument._dirInfoLocn2.FullName + @"\" + fileInfoPrimary_temp.Name)))
                        {
                            try
                            {
                                g_sFileName = fileInfoPrimary_temp.Name;
                                g_sCompleteFileName = fileInfoPrimary_temp.FullName;
                                File.Copy(fileInfoPrimary_temp.FullName, argument._dirInfoLocn2.FullName + @"\" + fileInfoPrimary_temp.Name);
                                bWorkerSync.ReportProgress(Convert.ToInt32(fileInfoPrimary_temp.Length / 1024));
                            }
                            catch (System.Exception ex)
                            {
                                MessageBox.Show(ex.Message + "\nAborting the operation");
                                e.Cancel = true;
                                return;
                            }
                        }
                        break;

                    case (int)enmSyncOption.AlwaysOverwrite:
                        if (!(File.Exists(argument._dirInfoLocn2.FullName + @"\" + fileInfoPrimary_temp.Name)))
                        {
                            try
                            {
                                g_sFileName = fileInfoPrimary_temp.Name;
                                g_sCompleteFileName = fileInfoPrimary_temp.FullName;
                                File.Copy(fileInfoPrimary_temp.FullName, argument._dirInfoLocn2.FullName + @"\" + fileInfoPrimary_temp.Name);
                                bWorkerSync.ReportProgress(Convert.ToInt32(fileInfoPrimary_temp.Length / 1024));
                            }
                            catch (System.Exception ex)
                            {
                                MessageBox.Show(ex.Message + "\nAborting the operation");
                                e.Cancel = true;
                                return;
                            }
                        }
                        else
                        {
                            //File.Replace(fileInfoPrimary_temp.FullName, argument._dirInfoLocn2.FullName + @"\" + fileInfoPrimary_temp.Name, argument._dirInfoLocn2.FullName + @"\" + fileInfoPrimary_temp.Name+".bak");
                            try
                            {
                                g_sFileName = fileInfoPrimary_temp.Name;
                                g_sCompleteFileName = fileInfoPrimary_temp.FullName;
                                File.Delete(argument._dirInfoLocn2.FullName + @"\" + fileInfoPrimary_temp.Name);
                                File.Copy(fileInfoPrimary_temp.FullName, argument._dirInfoLocn2.FullName + @"\" + fileInfoPrimary_temp.Name);
                            }
                            catch (System.Exception ex)
                            {
                                MessageBox.Show(ex.Message + "\nAborting the operation");
                                e.Cancel = true;
                                return;
                            }
                            bWorkerSync.ReportProgress(Convert.ToInt32(fileInfoPrimary_temp.Length / 1024));
                        }
                        break;

                    case (int)enmSyncOption.LatestVersion:
                        if (!(File.Exists(argument._dirInfoLocn2.FullName + @"\" + fileInfoPrimary_temp.Name)))
                        {
                            try
                            {
                                g_sFileName = fileInfoPrimary_temp.Name;
                                g_sCompleteFileName = fileInfoPrimary_temp.FullName;
                                File.Copy(fileInfoPrimary_temp.FullName, argument._dirInfoLocn2.FullName + @"\" + fileInfoPrimary_temp.Name);
                            }
                            catch (System.Exception ex)
                            {
                                MessageBox.Show(ex.Message + "\nAborting the operation");
                                e.Cancel = true;
                                return;
                            }
                            bWorkerSync.ReportProgress(Convert.ToInt32(fileInfoPrimary_temp.Length / 1024));
                        }
                        else
                        {
                            FileInfo tmpFInfoSrc = new FileInfo(fileInfoPrimary_temp.FullName);
                            FileInfo tmpFInfoDst = new FileInfo(argument._dirInfoLocn2.FullName + @"\" + fileInfoPrimary_temp.Name);
                            if ((tmpFInfoDst.LastWriteTimeUtc < tmpFInfoSrc.LastWriteTimeUtc))
                            {
                                try
                                {
                                    g_sFileName = fileInfoPrimary_temp.Name;
                                    g_sCompleteFileName = fileInfoPrimary_temp.FullName;
                                    //File.Replace(fileInfoPrimary_temp.FullName, argument._dirInfoLocn2.FullName + @"\" + fileInfoPrimary_temp.Name, argument._dirInfoLocn2.FullName + @"\" + fileInfoPrimary_temp.Name+".bak");
                                    File.Delete(argument._dirInfoLocn2.FullName + @"\" + fileInfoPrimary_temp.Name);
                                    File.Copy(fileInfoPrimary_temp.FullName, argument._dirInfoLocn2.FullName + @"\" + fileInfoPrimary_temp.Name);
                                }
                                catch (System.Exception ex)
                                {
                                    MessageBox.Show(ex.Message + "\nAborting the operation");
                                    e.Cancel = true;
                                    return;
                                }
                            }
                            bWorkerSync.ReportProgress(Convert.ToInt32(fileInfoPrimary_temp.Length / 1024));
                        }
                        break;

                }

            }
        }

        /// <summary>
        /// Recursive function, to create folders (if not present), copy files within the folders. We provide all the folders present in the
        /// root from the Async worker thread. We have logic to check the type of sync option we have chosen and we proceed accordingly
        /// </summary>
        /// <param name="dirInfoTemp">The dir info temp.</param>
        /// <param name="sSecondaryLocation">The s secondary location.</param>
        /// <param name="syncOptions">The sync options.</param>
        /// <param name="e">The <see cref="System.ComponentModel.DoWorkEventArgs"/> instance containing the event data.</param>
        private void recursiveDirectoryCalls(DirectoryInfo dirInfoTemp, String sSecondaryLocation,int syncOptions, DoWorkEventArgs e)
        {
            string sSecondaryLocation_Temp = string.Empty;
            DirectoryInfo[] dirInfoRecurTemp = dirInfoTemp.GetDirectories();
            if (dirInfoTemp.GetFiles().GetLength(0)>0)
            {

                FileInfo[] finfo = dirInfoTemp.GetFiles();

                foreach (FileInfo fInfo_tmp in finfo)
                {
                    if (bWorkerSync.CancellationPending)
                    {
                        e.Cancel = true;
                        return;
                    }

                    mseSyncWorkerLocker.WaitOne();

                    switch (syncOptions)
                    {
                        case (int)enmSyncOption.CopyNonExistent:
                            if (!(File.Exists(sSecondaryLocation +  @"\" + dirInfoTemp.Name + @"\" + fInfo_tmp.Name)))
                            {
                                long fileSize = fInfo_tmp.Length;
                                g_sFileName = fInfo_tmp.Name;
                                g_sCompleteFileName = fInfo_tmp.FullName;
                                File.Copy(fInfo_tmp.FullName, sSecondaryLocation + @"\" + dirInfoTemp.Name + @"\" + fInfo_tmp.Name);
                                while ((fileSize - 2147483647) >= 2147483647)
                                {
                                    fileSize = fileSize - 2147483647;  //Changed from filesize=finfo_tmp.length -x;
                                    bWorkerSync.ReportProgress(Convert.ToInt32(2147483647));
                                }
                                if (fileSize > 2147483647)
                                {
                                    bWorkerSync.ReportProgress(Convert.ToInt32(2147483647));
                                    bWorkerSync.ReportProgress(Convert.ToInt32(fileSize - 2147483647));
                                }
                                else
                                    bWorkerSync.ReportProgress(Convert.ToInt32(fileSize));
                            }

                            break;

                        case (int)enmSyncOption.AlwaysOverwrite:
                            if (!(File.Exists(sSecondaryLocation + @"\" + dirInfoTemp.Name + @"\" + fInfo_tmp.Name)))
                            {
                                long fileSize = fInfo_tmp.Length;
                                g_sFileName = fInfo_tmp.Name;
                                g_sCompleteFileName = fInfo_tmp.FullName;
                                File.Copy(fInfo_tmp.FullName, sSecondaryLocation + @"\" + dirInfoTemp.Name + @"\" + fInfo_tmp.Name);
                                while ((fileSize - 2147483647) >= 2147483647)
                                {
                                    fileSize = fileSize - 2147483647;
                                    bWorkerSync.ReportProgress(Convert.ToInt32(2147483647));
                                }
                                if (fileSize > 2147483647)
                                {
                                    bWorkerSync.ReportProgress(Convert.ToInt32(2147483647));
                                    bWorkerSync.ReportProgress(Convert.ToInt32(fileSize - 2147483647));
                                }
                                else
                                    bWorkerSync.ReportProgress(Convert.ToInt32(fileSize));
                            }
                            else
                            {
                                long fileSize = fInfo_tmp.Length;
                                g_sFileName = fInfo_tmp.Name;
                                g_sCompleteFileName = fInfo_tmp.FullName;
                                //File.Replace(fInfo_tmp.FullName, sSecondaryLocation + @"\" + testDirInfo.Parent.Name + @"\" + testDirInfo.Name + @"\" + fInfo_tmp.Name, sSecondaryLocation + @"\" + testDirInfo.Parent.Name + @"\" + testDirInfo.Name + @"\" + fInfo_tmp.Name+".bak");
                                File.Delete(sSecondaryLocation + @"\" + dirInfoTemp.Name + @"\" + fInfo_tmp.Name);
                                File.Copy(fInfo_tmp.FullName, sSecondaryLocation + @"\" + dirInfoTemp.Name + @"\" + fInfo_tmp.Name);
                                while ((fileSize - 2147483647) >= 2147483647)
                                {
                                    fileSize = fileSize - 2147483647;
                                    bWorkerSync.ReportProgress(Convert.ToInt32(2147483647));
                                }
                                if (fileSize > 2147483647)
                                {
                                    bWorkerSync.ReportProgress(Convert.ToInt32(2147483647));
                                    bWorkerSync.ReportProgress(Convert.ToInt32(fileSize - 2147483647));
                                }
                                else
                                    bWorkerSync.ReportProgress(Convert.ToInt32(fileSize));
                            }

                            break;

                        case (int)enmSyncOption.LatestVersion:
                            if (!(File.Exists(sSecondaryLocation + @"\" + dirInfoTemp.Name + @"\" + fInfo_tmp.Name)))
                            {
                                long fileSize = fInfo_tmp.Length;
                                g_sFileName = fInfo_tmp.Name;
                                g_sCompleteFileName = fInfo_tmp.FullName;
                                File.Copy(fInfo_tmp.FullName, sSecondaryLocation + @"\" + dirInfoTemp.Name + @"\" + fInfo_tmp.Name);
                                while ((fileSize - 2147483647) >= 2147483647)
                                {
                                    fileSize = fileSize - 2147483647;
                                    bWorkerSync.ReportProgress(Convert.ToInt32(2147483647));
                                }
                                if (fileSize > 2147483647)
                                {
                                    bWorkerSync.ReportProgress(Convert.ToInt32(2147483647));
                                    bWorkerSync.ReportProgress(Convert.ToInt32(fileSize - 2147483647));
                                }
                                else
                                    bWorkerSync.ReportProgress(Convert.ToInt32(fileSize));
                            }
                            else
                            {
                                long fileSize = fInfo_tmp.Length;
                                FileInfo tmpfInfoSrc = new FileInfo(fInfo_tmp.FullName);
                                FileInfo tmpfInfoDst = new FileInfo(sSecondaryLocation + @"\" + dirInfoTemp.Name + @"\" + fInfo_tmp.Name);
                                if (tmpfInfoDst.LastWriteTimeUtc < tmpfInfoSrc.LastWriteTimeUtc)
                                {
                                    g_sFileName = fInfo_tmp.Name;
                                    g_sCompleteFileName = fInfo_tmp.FullName;
                                    //File.Replace(fInfo_tmp.FullName, sSecondaryLocation + @"\" + testDirInfo.Parent.Name + @"\" + testDirInfo.Name + @"\" + fInfo_tmp.Name, sSecondaryLocation + @"\" + testDirInfo.Parent.Name + @"\" + testDirInfo.Name + @"\" + fInfo_tmp.Name + ".bak");
                                    File.Delete(sSecondaryLocation + @"\" + dirInfoTemp.Name + @"\" + fInfo_tmp.Name);
                                    File.Copy(fInfo_tmp.FullName, sSecondaryLocation + @"\" + dirInfoTemp.Name + @"\" + fInfo_tmp.Name);
                                }
                                while ((fileSize - 2147483647) >= 2147483647)
                                {
                                    fileSize = fileSize - 2147483647;
                                    bWorkerSync.ReportProgress(Convert.ToInt32(2147483647));
                                }
                                if (fileSize > 2147483647)
                                {
                                    bWorkerSync.ReportProgress(Convert.ToInt32(2147483647));
                                    bWorkerSync.ReportProgress(Convert.ToInt32(fileSize - 2147483647));
                                }
                                else
                                    bWorkerSync.ReportProgress(Convert.ToInt32(fileSize));
                            }

                            break;
                    }
                }
            }

            #region We work with Folders/Directories here. Work like creating folders in congruent paths
            foreach (DirectoryInfo testDirInfo in dirInfoRecurTemp)
            {
                if (bWorkerSync.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }

                mseSyncWorkerLocker.WaitOne();
                if (!(Directory.Exists(sSecondaryLocation + @"\" + testDirInfo.Parent.Name + @"\" + testDirInfo.Name)))
                {
                    Directory.CreateDirectory(sSecondaryLocation + @"\" + testDirInfo.Parent.Name + @"\" + testDirInfo.Name);
                }

                sSecondaryLocation_Temp = sSecondaryLocation + @"\" + testDirInfo.Parent.Name;
                recursiveDirectoryCalls(testDirInfo, sSecondaryLocation_Temp, syncOptions, e);
            }
            #endregion
        }

        /// <summary>
        /// Method to handle Progress report for the bWorkerSync worker. Here I update the Progress bar
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.ComponentModel.ProgressChangedEventArgs"/> instance containing the event data.</param>
        private void bWorkerSync_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            iPercentComplete = (int)(((double)progressBarSync.Value / (double)progressBarSync.Maximum) * 100);
            progressBarSync.CreateGraphics().DrawString(iPercentComplete.ToString() + "%", new Font("Arial", (float)8.25, FontStyle.Regular), Brushes.Black, new PointF(progressBarSync.Width / 2 - 10, progressBarSync.Height / 2 - 7));
            progressBarSync.Value += e.ProgressPercentage / 1024;
            lnklblCurrentFile.Text = g_sCompleteFileName;
            try
            {
                FnFSyncMainForm.ActiveForm.Text = "FNFSync" + " - " + iPercentComplete + "% complete";
                this.notifyIcon1.Text = "FnFSync-0354" + " - " + iPercentComplete + "% complete";
                //Commenting below line as it unneccessarily increasing time for overall sync
                //listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + iPercentComplete + "% complete till now." + " " + g_sFileName + " is the last file syncronized");

            }
            catch
            {
            }
            this.notifyIcon1.Text = "FnFSync-0354" + " - " + iPercentComplete + "% complete";
            if (level2ToolStripMenuItem.Checked || l3ToolStripMenuItem.Checked)
            {
                if (!(listBoxMessageCenter.Items.Contains(System.DateTime.Now + "\t" + iPercentComplete + "% complete till now." + " " + g_sFileName + " is the last file syncronized")))
                    listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + iPercentComplete + "% complete till now." + " " + g_sFileName + " is the last file syncronized");
            }

        }


        /// <summary>
        /// Method to handle the "completed" event for the bWorkerSync background worker. we also print messages like
        /// if the sync succeeded/failed/errorred.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.ComponentModel.RunWorkerCompletedEventArgs"/> instance containing the event data.</param>
        private void bWorkerSync_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            gBoxButtons.Enabled = true;
            gBoxSyncOptions.Enabled = true;
            
            tEndTime = DateTime.Now;
            TimeSpan ts = tEndTime - tStartTime;

            if (e.Cancelled)
            {
                notifyIcon1.BalloonTipText = lblStatusMsg.Text = "Syncronization is cancelled." + " Took " + ts.TotalSeconds + " seconds effectively";
                notifyIcon1.ShowBalloonTip(5000, "Cancelled", notifyIcon1.BalloonTipText, ToolTipIcon.Info);
                listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + "Syncronization is cancelled." + " Took " + ts.TotalSeconds + " seconds effectively");

            }
            else if (e.Error != null)
            {
                notifyIcon1.BalloonTipText = lblStatusMsg.Text = "Syncronization errorrd out." + " Took " + ts.TotalSeconds + " seconds effectively";
                notifyIcon1.ShowBalloonTip(5000, "Error", notifyIcon1.BalloonTipText, ToolTipIcon.Error);
                listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + "Syncronization errorrd out." + " Took " + ts.TotalSeconds + " seconds effectively");

            }
            else
            {
                if (rBtn2WaySync.Checked && oFolderSync.TwoWaySyncInitiationComplete == false)
                {
                    notifyIcon1.BalloonTipText = lblStatusMsg.Text = "Syncronization Phase I is complete." + " Took " + ts.TotalSeconds + " seconds effectively. Phase II Sync in progress...";
                    listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + "Syncronization Phase I is complete." + " Took " + ts.TotalSeconds + " seconds effectively. Phase II Sync in progress...");

                    notifyIcon1.ShowBalloonTip(5000, "Phase I Complete", notifyIcon1.BalloonTipText, ToolTipIcon.Info);
                    try
                    {
                        FnFSyncMainForm.ActiveForm.Text = "FNFSync - Phase I Syncronization complete. Phase II in progress...";
                    }
                    catch
                    {
                    }

                }
                else
                {
                    //progressBarSync.Value = progressBarSync.Maximum;
                    notifyIcon1.BalloonTipText = lblStatusMsg.Text = "Syncronization is complete." + " Took " + ts.TotalSeconds + " seconds effectively";
                    listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + "Syncronization is complete." + " Took " + ts.TotalSeconds + " seconds effectively");

                    notifyIcon1.ShowBalloonTip(5000, "Complete", notifyIcon1.BalloonTipText, ToolTipIcon.Info);
                    try
                    {
                        FnFSyncMainForm.ActiveForm.Text = "FNFSync - Syncronization complete";
                        if (chkBxCloseApp.Checked)
                        {
                            this.Close();
                        }
                    }
                    catch
                    {
                    }
                }
            }

            btnSyncNonExistingFiles.Enabled = true;
            btnStopSync.Enabled = false;
            btnResumeSync.Enabled = false;
            btnPauseSync.Enabled = false;
            bWorkerFolder1Size.RunWorkerAsync(oFolderSync.diDirInfoLocn1);
            bWorkerFolder2Size.RunWorkerAsync(oFolderSync.diDirInfoLocn2);
            if (rBtnSyncUp.Checked)
            {
                oFolderSync.sPrimaryLocation = txtFolderLocn1.Text;
                oFolderSync.sSecondaryLocation = txtFolderLocn2.Text;
                progressBarSync.Value = progressBarSync.Maximum;
                if (chkBxCloseApp.Checked)
                    this.Close();
            }
            else if (rBtn2WaySync.Checked && oFolderSync.TwoWaySyncInitiationComplete == false && e.Cancelled == false && e.Error == null)
            {
                oFolderSync.sPrimaryLocation = txtFolderLocn1.Text;
                oFolderSync.sSecondaryLocation = txtFolderLocn2.Text;
                Sync(oFolderSync.diDirInfoLocn1, oFolderSync.diDirInfoLocn2);
                oFolderSync.TwoWaySyncInitiationComplete = true;
            }
            else
            {
                progressBarSync.Value = progressBarSync.Maximum;
                if (chkBxCloseApp.Checked)
                    this.Close();
            }
            this.notifyIcon1.Text = "FnFSync-0354";
        }

        /// <summary>
        /// Handles the click event for the Button Validate Location for the Primary location. Here we check
        /// if the complete path is already present, if not, we try to create the path. If either of the above succeeds
        /// we enable the flag saying that Location is valid
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnValidateLocn1_Click(object sender, EventArgs e)
        {
            try
            {
                FnFSyncMainForm.ActiveForm.Text = "FNFSync";
            }
            catch
            {
            }

            progressBarSync.Value = 0;
            if (!Directory.Exists(txtFolderLocn1.Text))
            {
                try
                {
                    Directory.CreateDirectory(txtFolderLocn1.Text);
                }
                catch
                {
                    lblStatusMsg.Text = "Primary Folder location is invalid. Please enter a valid path";
                    listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + "Primary Location is invalid.");

                    oFolderSync.bFolderLocation1Validated = false;
                    txtFolderLocn1.BackColor = System.Drawing.Color.Salmon;
                    return; //returning so that we dont perform any more operations in this function
                }
            }

            lblStatusMsg.Text = "Primary Folder location is valid";
            listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + "Primary Location is valid");

            //Not enabled in this version
            //chkbxMonitorPrimary.Enabled = true;

            oFolderSync.bFolderLocation1Validated = true;
            txtFolderLocn2.Enabled = true;
            btnSelectFolderLocn2.Enabled = true;
            btnValidateLocn2.Enabled = true;
            oFolderSync.sPrimaryLocation = txtFolderLocn1.Text;
            txtFolderLocn1.BackColor = System.Drawing.Color.DarkSeaGreen;
            fswPrimaryFileLocation.Path = txtFolderLocn1.Text;

            oFolderSync.diDirInfoLocn1 = new DirectoryInfo(oFolderSync.sPrimaryLocation);
            lblFolder1Size.Text = "calculating...";
            while (!bWorkerFolder1Size.IsBusy)
                bWorkerFolder1Size.RunWorkerAsync(oFolderSync.diDirInfoLocn1);

            //Populate Treeview if FTP is not selected.

            int FolderType = (int)enmFolderType.Network;

            populateTreeView(FTPTree1, FolderType);

        }


        /// <summary>
        /// Handles the click event for the Button Validate Location for the Secondary location. Here we check
        /// if the complete path is already present, if not, we try to create the path. If either of the above succeeds
        /// we enable the flag saying that Location is valid
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnValidateLocn2_Click(object sender, EventArgs e)
        {
            try
            {
                FnFSyncMainForm.ActiveForm.Text = "FNFSync";
            }
            catch
            {
            }
            progressBarSync.Value = 0;
            if (!Directory.Exists(txtFolderLocn2.Text))
            {
                try
                {
                    Directory.CreateDirectory(txtFolderLocn2.Text);
                }
                catch
                {
                    lblStatusMsg.Text = "Secondary Folder location is invalid. Please enter a valid path";
                    listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + "Secondary Folder Location is invalid.");

                    oFolderSync.bFolderLocation2Validated = false;
                    txtFolderLocn2.BackColor = System.Drawing.Color.Salmon;
                    return;
                }

            }

            lblStatusMsg.Text = "Secondary Folder location is valid";
            listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + "Secondary Folder Location is valid");

            //Not enabled in thie version
            //chlbxMonitorSecondary.Enabled = true;

            oFolderSync.bFolderLocation2Validated = true;
            oFolderSync.sSecondaryLocation = txtFolderLocn2.Text.ToString();
            txtFolderLocn2.BackColor = System.Drawing.Color.DarkSeaGreen;
            fswSecondaryFileLocation.Path = txtFolderLocn2.Text;

            oFolderSync.diDirInfoLocn2 = new DirectoryInfo(oFolderSync.sSecondaryLocation);
            lblFolder2Size.Text = "calculating...";
            while (!bWorkerFolder2Size.IsBusy)
                bWorkerFolder2Size.RunWorkerAsync(oFolderSync.diDirInfoLocn2);

        }


        /// <summary>
        /// Method for handling TextChange event for the text box for Primary File share
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void txtFolderLocn1_TextChanged(object sender, EventArgs e)
        {
            FnFSyncMainForm.ActiveForm.Text = "FNFSync";
            progressBarSync.Value = 0;
            txtFolderLocn1.BackColor = SystemColors.Window;
            chkbxMonitorPrimary.Checked = false;
            chkbxMonitorPrimary.Enabled = false;
            if (txtFolderLocn1.Text.Length > 0)
            {
                btnValidateLocn1.Enabled = true;
            }
            else
            {
                btnValidateLocn1.Enabled = false;
            }
        }

        /// <summary>
        /// Method for handling TextChange event for the text box for Secondary File share
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void txtFolderLocn2_TextChanged(object sender, EventArgs e)
        {
            FnFSyncMainForm.ActiveForm.Text = "FNFSync";
            progressBarSync.Value = 0;
            txtFolderLocn2.BackColor = SystemColors.Window;
            chlbxMonitorSecondary.Checked = false;
            chlbxMonitorSecondary.Enabled = false;

            if (txtFolderLocn2.Text.Length > 0)
            {
                btnValidateLocn2.Enabled = true;   
            }
            else
            {
                btnValidateLocn2.Enabled = false;
            }
        }

        /// <summary>
        /// Background Worker - bWorkerFolder1Size- Aync work. Its work is to calculate the size of each file in each subdirectory
        /// and find the total size of the folder
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.ComponentModel.DoWorkEventArgs"/> instance containing the event data.</param>
        private void bWorkerFolder1Size_DoWork(object sender, DoWorkEventArgs e)
        {
            DirectoryInfo argument = e.Argument as DirectoryInfo;
            List<string> result = new List<string>();

            // 2.
            // Store a stack of our directories.
            Stack<string> stack = new Stack<string>();

            // 3.
            // Add initial directory.
            stack.Push(argument.FullName);

            // 4.
            // Continue while there are directories to process
            while (stack.Count > 0)
            {
                // A.
                // Get top directory
                string dir = stack.Pop();

                try
                {
                    // B
                    // Add all files at this directory to the result List.
                    result.AddRange(Directory.GetFiles(dir, "*.*"));

                    // C
                    // Add all directories at this directory.
                    foreach (string dn in Directory.GetDirectories(dir))
                    {
                        stack.Push(dn);
                    }
                }
                catch
                {
                    // D
                    // Could not open the directory
                }
            }
            long sizeInKiloBytes = 0;
            List<String> dirs = result;
            foreach (string p in dirs)
            {
                try
                {
                    FileInfo fs = new FileInfo(p);
                    sizeInKiloBytes += fs.Length / 1024;
                }
                catch
                {
                    //lblStatusMsg.Text = ex.Message;
                }
                                    
                bWorkerFolder1Size.ReportProgress(Convert.ToInt32(sizeInKiloBytes));
            }
            e.Result = sizeInKiloBytes;
        }

        /// <summary>
        /// Background Worker Async work for the job of calculating the size of the Primary Folder. We are also updating the
        /// progress bar's maximum value as well
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.ComponentModel.ProgressChangedEventArgs"/> instance containing the event data.</param>
        private void bWorkerFolder1Size_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            lblFolder1Size.Text = e.ProgressPercentage + " KB... and calculating";
            oFolderSync.iPrimaryFolderSize = Convert.ToInt64(e.ProgressPercentage);
            progressBarSync.Maximum = Convert.ToInt32(oFolderSync.iPrimaryFolderSize);
        }

        /// <summary>
        /// Background Worker -bWorkerFolder1Size- complete event. Here we update the final size of the Folder in the
        /// iPrimaryFolderSize member of the Class cFolderSync
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.ComponentModel.RunWorkerCompletedEventArgs"/> instance containing the event data.</param>
        private void bWorkerFolder1Size_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            lblFolder1Size.Text = Convert.ToInt32(e.Result) + " KB.";
            oFolderSync.iPrimaryFolderSize = Convert.ToInt64(e.Result);
        }

        /// <summary>
        /// Background Worker - bWorkerFolder1Size- Aync work. Its work is to calculate the size of each file in each subdirectory
        /// and find the total size of the folder
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.ComponentModel.DoWorkEventArgs"/> instance containing the event data.</param>
        private void bWorkerFolder2Size_DoWork(object sender, DoWorkEventArgs e)
        {
            DirectoryInfo argument = e.Argument as DirectoryInfo;
            List<string> result = new List<string>();

            // 2.
            // Store a stack of our directories.
            Stack<string> stack = new Stack<string>();

            // 3.
            // Add initial directory.
            stack.Push(argument.FullName);

            // 4.
            // Continue while there are directories to process
            while (stack.Count > 0)
            {
                // A.
                // Get top directory
                string dir = stack.Pop();

                try
                {
                    // B
                    // Add all files at this directory to the result List.
                    result.AddRange(Directory.GetFiles(dir, "*.*"));

                    // C
                    // Add all directories at this directory.
                    foreach (string dn in Directory.GetDirectories(dir))
                    {
                        stack.Push(dn);
                    }
                }
                catch
                {
                    // D
                    // Could not open the directory
                }
            }
            long sizeInKiloBytes = 0;
            List<String> dirs = result;
            foreach (string p in dirs)
            {
                try
                {
                    FileInfo fs = new FileInfo(p);
                    sizeInKiloBytes += fs.Length / 1024;
                }
                catch
                {
                }
                bWorkerFolder2Size.ReportProgress(Convert.ToInt32(sizeInKiloBytes));
            }
            e.Result = sizeInKiloBytes;
        }

        /// <summary>
        /// Background worker -bWorkerFolder2Size- Progress change Event. We can access Windows control from here
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.ComponentModel.ProgressChangedEventArgs"/> instance containing the event data.</param>
        private void bWorkerFolder2Size_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            lblFolder2Size.Text = e.ProgressPercentage + "KB... and calculating";
            oFolderSync.iSecondaryFolderSize = Convert.ToInt64(e.ProgressPercentage);
            progressBarSync.Maximum = Convert.ToInt32(oFolderSync.iSecondaryFolderSize);
        }

        /// <summary>
        /// Background Worker -bWorkerFolder2Size- complete event. Here we update the final size of the Folder in the
        /// iPrimaryFolderSize member of the Class cFolderSync
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.ComponentModel.RunWorkerCompletedEventArgs"/> instance containing the event data.</param>
        private void bWorkerFolder2Size_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            lblFolder2Size.Text = Convert.ToInt32((e.Result)) + " KB.";
            oFolderSync.iSecondaryFolderSize = Convert.ToInt64(e.Result);
        }

        /// <summary>
        /// Method for handling event when we check/uncheck the 2Way Sync button on the frame
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void rBtn2WaySync_CheckedChanged(object sender, EventArgs e)
        {
            FnFSyncMainForm.ActiveForm.Text = "FNFSync";
            if (rBtn2WaySync.Checked)
            {
                rBtnAlwaysOverwrite.Checked = false;
                rBtnAlwaysOverwrite.Enabled = false;
                rBtnCopyNonExistent.Checked = true;

                chkbxMonitorPrimary.Enabled = false;
                chlbxMonitorSecondary.Enabled = false;
            }
            else
                rBtnAlwaysOverwrite.Enabled = true;
        }


        /// <summary>
        /// Handles the Click event of the btnBrowseLocn1 control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnBrowseLocn1_Click(object sender, EventArgs e)
        {
            Process.Start("explorer.exe", txtFolderLocn1.Text);
            if (l3ToolStripMenuItem.Checked)
            {
                listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + txtFolderLocn1.Text + " opened in explorer by user.");
            }
        }
        /// <summary>
        /// Handles the Click event of the openLocationToolStripMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void openLocationToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Process.Start("explorer.exe", txtFolderLocn1.Text);
            if (l3ToolStripMenuItem.Checked)
            {
                listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + txtFolderLocn1.Text + " opened in explorer by user.");
            }
        }
        /// <summary>
        /// Handles the Click event of the emptyLocationToolStripMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void emptyLocationToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Directory.Delete(txtFolderLocn1.Text, true);
            lblFolder1Size.Text = "calculating...";
            while (!bWorkerFolder1Size.IsBusy)
                bWorkerFolder1Size.RunWorkerAsync(oFolderSync.diDirInfoLocn1);

            Directory.CreateDirectory(txtFolderLocn1.Text);
        }


        /// <summary>
        /// Handles the Click event of the btnBrowseLocn2 control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void btnBrowseLocn2_Click(object sender, EventArgs e)
        {
            Process.Start("explorer.exe", txtFolderLocn2.Text);
            if (l3ToolStripMenuItem.Checked)
            {
                listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + txtFolderLocn2.Text + " opened in explorer by user.");
            }
        }
        /// <summary>
        /// Handles the Click event of the openLocationToolStripMenuItem1 control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void openLocationToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            Process.Start("explorer.exe", txtFolderLocn2.Text);
            if (l3ToolStripMenuItem.Checked)
            {
                listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + txtFolderLocn2.Text + " opened in explorer by user.");
            }
        }
        /// <summary>
        /// Handles the Click event of the emptyLocationToolStripMenuItem1 control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void emptyLocationToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            Directory.Delete(txtFolderLocn2.Text, true);
            lblFolder2Size.Text = "calculating...";
            while (!bWorkerFolder2Size.IsBusy)
                bWorkerFolder2Size.RunWorkerAsync(oFolderSync.diDirInfoLocn2);

            Directory.CreateDirectory(txtFolderLocn2.Text);
        }

        private void emptyMessageCenterToolStripMenuItem_Click(object sender, EventArgs e)
        {
            listBoxMessageCenter.Items.Clear();
        }

        private void level2ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (!level2ToolStripMenuItem.Checked)
            {
                level2ToolStripMenuItem.Checked = true;
                level1ToolStripMenuItem.Checked = false;
                l3ToolStripMenuItem.Checked = false;
                listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + "Verbose Level 2 activated");
                toolTip1.SetToolTip(this.listBoxMessageCenter, "Message Center @ Verbose Level 2");
            }
            else
            {
                level2ToolStripMenuItem.Checked = false;
                level1ToolStripMenuItem.Checked = true;
                listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + "Reverted to default verbose level");
                toolTip1.SetToolTip(this.listBoxMessageCenter, "Message Center @ Verbose Level 1");
            }

        }

        private void l3ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (!l3ToolStripMenuItem.Checked)
            {
                l3ToolStripMenuItem.Checked = true;
                level1ToolStripMenuItem.Checked = false;
                level2ToolStripMenuItem.Checked = false;
                listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + "Verbose Level 3 activated");
                toolTip1.SetToolTip(this.listBoxMessageCenter, "Message Center @ Verbose Level 3");
            }
            else
            {
                l3ToolStripMenuItem.Checked = false;
                level1ToolStripMenuItem.Checked = true;
                listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + "Reverted to default verbose level");
                toolTip1.SetToolTip(this.listBoxMessageCenter, "Message Center @ Verbose Level 1");
            }
        }

        private void level1ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (!level1ToolStripMenuItem.Checked)
            {
                level1ToolStripMenuItem.Checked = true;
                level2ToolStripMenuItem.Checked = false;
                l3ToolStripMenuItem.Checked = false;

                toolTip1.SetToolTip(this.listBoxMessageCenter, "Message Center @ Verbose Level 1");
                listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + "Verbose Level 1 activated");
            }
        }

        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            Show();
            WindowState = FormWindowState.Normal;
        }

        private void lnklblCurrentFile_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            Process.Start("Explorer.exe", lnklblCurrentFile.Text);
            if (l3ToolStripMenuItem.Checked)
            {
                listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + lnklblCurrentFile.Text + " opened by user.");
            }
        }

        private void saveToFileAndPurgeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //MessageBox.Show("Not yet implemented", "No Functionality provided", MessageBoxButtons.OK);
            StreamWriter strWrt;

            if (!File.Exists(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\" + "FnFSyncMessageCenter.log"))
            {
                strWrt = File.CreateText(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\" + "FnFSyncMessageCenter.log");
            }
            else
            {
                strWrt = File.AppendText(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\" + "FnFSyncMessageCenter.log");
            }
            
            strWrt.WriteLine(DateTime.Now);
            strWrt.WriteLine("=====================");
            strWrt.WriteLine("");
            for(int counter=0;counter<listBoxMessageCenter.Items.Count;counter++)
            {
                strWrt.WriteLine(listBoxMessageCenter.Items[counter]);
            }
            strWrt.WriteLine("=====================");
            strWrt.WriteLine("");
            strWrt.WriteLine("");
            strWrt.WriteLine("");
            
            strWrt.Close();
            listBoxMessageCenter.Items.Clear();

            if (l3ToolStripMenuItem.Checked)
            {
                listBoxMessageCenter.Items.Add(System.DateTime.Now + "\t" + "Logs saved to file at My Documents and message center is cleared.");
            }
        }

        private void btnSaveSettings_Click(object sender, EventArgs e)
        {
            if (rBtn2WaySync.Checked)
            {
                FNFSync.Properties.Settings.Default.SyncDirections = "Two Way Sync";
                FNFSync.Properties.Settings.Default.Save();
            }
            else if (rBtnSyncUp.Checked)
            {
                FNFSync.Properties.Settings.Default.SyncDirections = "Sync Up";
                FNFSync.Properties.Settings.Default.Save();
            }
            else if (rBtnDown.Checked)
            {
                FNFSync.Properties.Settings.Default.SyncDirections = "Sync Down";
                FNFSync.Properties.Settings.Default.Save();
            }

            if (rBtnAlwaysOverwrite.Checked)
            {
                FNFSync.Properties.Settings.Default.SyncOptions = "Always Overwrite";
                FNFSync.Properties.Settings.Default.Save();
            }
            else if (rBtnCopyNonExistent.Checked)
            {
                FNFSync.Properties.Settings.Default.SyncOptions = "Copy Non-Existent";
                FNFSync.Properties.Settings.Default.Save();
            }
            else if (rBtnLatestVersion.Checked)
            {
                FNFSync.Properties.Settings.Default.SyncOptions = "Overwrite Older Version";
                FNFSync.Properties.Settings.Default.Save();
            }

            if (level1ToolStripMenuItem.Checked)
            {
                FNFSync.Properties.Settings.Default.VerboseLevel = "Level 1";
                FNFSync.Properties.Settings.Default.Save();
            }
            else if(level2ToolStripMenuItem.Checked)
            {
                FNFSync.Properties.Settings.Default.VerboseLevel = "Level 2";
                FNFSync.Properties.Settings.Default.Save();
            }
            else if(l3ToolStripMenuItem.Checked)
            {
                FNFSync.Properties.Settings.Default.VerboseLevel = "Level 3";
                FNFSync.Properties.Settings.Default.Save();
            }

            if (chkBxCloseApp.Checked)
            {
                FNFSync.Properties.Settings.Default.CloseOnComplete = "Yes";
                FNFSync.Properties.Settings.Default.Save();
            }
            else
            {
                FNFSync.Properties.Settings.Default.CloseOnComplete = "No";
                FNFSync.Properties.Settings.Default.Save();
            }

            FNFSync.Properties.Settings.Default.PrimaryLocation = txtFolderLocn1.Text;
            FNFSync.Properties.Settings.Default.Save();
            FNFSync.Properties.Settings.Default.SecondaryLocation = txtFolderLocn2.Text;
            FNFSync.Properties.Settings.Default.Save();
        }

        private void chkbxMonitorPrimary_CheckedChanged(object sender, EventArgs e)
        {
            
        }

        private void chkbxStartup_CheckedChanged(object sender, EventArgs e)
        {
            if (chkbxStartup.Checked)
            {
                //Code to Enable startup
                appStartup.SetValue("FNFSync", Application.ExecutablePath.ToString());
            }
            else
            {
                //code to disable startup
                appStartup.DeleteValue("FNFSync", false);
            }
        }

        private void rBtnDown_CheckedChanged(object sender, EventArgs e)
        {
            if (rBtnDown.Checked)
            {
                chkbxMonitorPrimary.Enabled = true;
            }
            else
            {
                chkbxMonitorPrimary.Enabled = false;
            }
        }

        private void rBtnSyncUp_CheckedChanged(object sender, EventArgs e)
        {
            if (rBtnSyncUp.Checked)
            {
                chlbxMonitorSecondary.Enabled = true;
            }
            else
            {
                chlbxMonitorSecondary.Enabled = false;
            }
        }

        private void btnResetFTPPrimary_Click(object sender, EventArgs e)
        {
            txtFTPPrimary.Text = string.Empty;
            txtFTPPrimaryPass.Text = string.Empty;
            txtFTPPrimaryUser.Text = string.Empty;

            txtFTPPrimary.Focus();
        }

        private void btnResetFTPSecondary_Click(object sender, EventArgs e)
        {
            txtFTPSecondary.Text = string.Empty;
            txtFTPSecondaryPass.Text = string.Empty;
            txtFTPSecondaryUser.Text = string.Empty;

            txtFTPSecondary.Focus();
        }

        private void cmbFolderTypePrimary_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cmbFolderTypePrimary.SelectedIndex == 2)
            {
                splitPrimary.Panel1.Enabled = true;

                chkbxMonitorPrimary.Enabled = false;
                btnBrowseLocn1.Enabled = false;
                btnSelectFolderLocn1.Enabled = false;
                btnValidateLocn1.Enabled = false;
                txtFolderLocn1.Enabled = false;

                if (cmbFolderTypeSecondary.SelectedIndex != 2)
                {
                    int tmp = cmbFolderTypeSecondary.SelectedIndex;
                    cmbFolderTypeSecondary.SelectedIndex = 2;
                    cmbFolderTypeSecondary.SelectedIndex = tmp;
                }
                
            }
            else
            {
                splitPrimary.Panel1.Enabled = false;

                chkbxMonitorPrimary.Enabled = true;
                btnBrowseLocn1.Enabled = true;
                btnSelectFolderLocn1.Enabled = true;
                btnValidateLocn1.Enabled = true;
                txtFolderLocn1.Enabled = true;
            }
        }

        private void cmbFolderTypeSecondary_SelectedIndexChanged(object sender, EventArgs e)
        {
            if(cmbFolderTypeSecondary.SelectedIndex==2)
            {
                splitSecondary.Panel1.Enabled = true;

                chlbxMonitorSecondary.Enabled = false;
                btnBrowseLocn2.Enabled = false;
                btnValidateLocn2.Enabled = false;
                btnSelectFolderLocn2.Enabled = false;
                txtFolderLocn2.Enabled = false;
            }
            else
            {
                splitSecondary.Panel1.Enabled = false;

                chlbxMonitorSecondary.Enabled = true;
                btnBrowseLocn2.Enabled = true;
                btnValidateLocn2.Enabled = true;
                btnSelectFolderLocn2.Enabled = true;
                txtFolderLocn2.Enabled = true;
            }


        }


    }

}
